package com.hmkj.core.service.order.impl;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.hmkj.common.baseMapper.GenericMapper;
import com.hmkj.common.entity.dtgrid.DtGrid;
import com.hmkj.common.entity.dtgrid.QueryUtils;
import com.hmkj.common.utils.*;
import com.hmkj.core.constant.CacheID;
import com.hmkj.core.constant.ConfigNID;
import com.hmkj.core.constant.Constant;
import com.hmkj.core.constant.Enum;
import com.hmkj.core.eolinker.endpoints.QuotationEndpoint;
import com.hmkj.core.eolinker.models.ModelRealTime;
import com.hmkj.core.exception.BussinessException;
import com.hmkj.core.exception.DtGridException;
import com.hmkj.core.mapper.account.AccountLogMapper;
import com.hmkj.core.mapper.account.AccountMapper;
import com.hmkj.core.mapper.invest.InvestMapper;
import com.hmkj.core.mapper.investAccountLog.InvestAccountLogMapper;
import com.hmkj.core.mapper.order.OrderMapper;
import com.hmkj.core.model.BuyModel;
import com.hmkj.core.model.order.OrderModel;
import com.hmkj.core.po.account.Account;
import com.hmkj.core.po.account.AccountLog;
import com.hmkj.core.po.accountLog.PlatAccountLog;
import com.hmkj.core.po.invest.Invest;
import com.hmkj.core.po.investAccountLog.InvestAccountLog;
import com.hmkj.core.po.order.Order;
import com.hmkj.core.po.order.OrderOperation;
import com.hmkj.core.po.system.Admin;
import com.hmkj.core.po.user.User;
import com.hmkj.core.service.account.AccountLogService;
import com.hmkj.core.service.account.AccountService;
import com.hmkj.core.service.accountLog.PlatAccountLogService;
import com.hmkj.core.service.cache.RedisService;
import com.hmkj.core.service.order.OrderOperationService;
import com.hmkj.core.service.order.OrderService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.*;

/**
 * 用户点买策略订单业务相关Service接口实现<br>
 *
 * @author lizhijie
 * @ClassName: OrderServiceImpl
 * @date 2018-07-05 05:19:00
 */
@Service
@Scope("prototype")
@Transactional(rollbackFor = Exception.class)
public class OrderServiceImpl implements OrderService {

    @Resource
    private OrderMapper orderMapper;
    @Resource
    private RedisService redisService;
    @Resource
    private AccountMapper accountMapper;
    @Resource
    private InvestMapper investMapper;
    @Resource
    private AccountLogMapper accountLogMapper;
    @Resource
    InvestAccountLogMapper investAccountLogMapper;
    @Resource
    private AccountService accountService;
    @Resource
    private AccountLogService accountLogService;
    @Resource
    private PlatAccountLogService platAccountLogService;
    @Resource
    private OrderOperationService orderOperationService;

    @Override
    public GenericMapper<Order, Integer> _getMapper() {
        return orderMapper;
    }

    @Override
    public BigDecimal getOrderCurrentProfit(Integer id) {
        try {
            Order order = orderMapper.selectByPrimaryKey(id);
            //计算买入市值
            BigDecimal buyMoney = order.getBuyDealPrice().multiply(new BigDecimal(order.getBuyDealNumber()));
            //计算当前市值
            ModelRealTime model = QuotationEndpoint.realtime(order.getEquityCode());
            if (null == model) {
                System.out.println("计算出错: 当前股票(" + order.getEquityCode() + ") 获取最新价出错...");
                model = QuotationEndpoint.realtime(order.getEquityCode());
            }

            if (PriceHelper.isLessThanOrEquals(new BigDecimal(model.getLast_price()), BigDecimal.ZERO)) {
                //停盘
                if (model.getStatus().equals("1") || model.getStatus().equals("2")) {
                    //1.111是停牌的意思
                    return new BigDecimal(1.111);
                }
            }
            if (PriceHelper.isLessThan(new BigDecimal(model.getLast_price()), new BigDecimal(model.getPrev_price()).multiply(BigDecimal.valueOf(0.5)))) {
                //停盘
                if (model.getStatus().equals("1") || model.getStatus().equals("2")) {
                    //1.111是停牌的意思
                    return new BigDecimal(1.111);
                }
            }
            if (model.getStatus().equals("1") || model.getStatus().equals("2")) {
                return new BigDecimal(1.111);
            }
            BigDecimal nowMoney = new BigDecimal(order.getBuyDealNumber()).multiply(new BigDecimal(model.getLast_price()));
            //计算当前盈亏(盈亏 = 当前市值 - 买入市值)
            return nowMoney.subtract(buyMoney);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return BigDecimal.ZERO;
    }

    @Override
    public void doOrderBack(Order order, Admin admin) throws Exception {
        if (null == order.getBuyDealNumber()) {
            throw new BussinessException("成交数量不能为空");
        } else if (order.getBuyDealNumber().toString().length() > 10) {
            throw new BussinessException("成交数量长度不能超过10位");
        } else if (!ValidateUtils.isPrice(order.getBuyDealNumber().toString())) {
            throw new BussinessException("成交数量格式不正确");
        } else if (null == order.getBuyDealPrice()) {
            throw new BussinessException("成交价格不能为空");
        } else if (order.getBuyDealPrice().compareTo(BigDecimal.ZERO) < 1) {
            throw new BussinessException("成交价格必须大于0");
        } else if (order.getBuyDealPrice().toString().length() > 10) {
            throw new BussinessException("成交价格长度不能超过10位");
        } else if (!ValidateUtils.isPrice(order.getBuyDealPrice().toString())) {
            throw new BussinessException("成交价格格式不正确");
        }
        //止盈 = 点买金额 X 止盈比例
        BigDecimal profitDeposit = (order.getTradeCredit().multiply(redisService.get(ConfigNID.STOP_PROFIT_LINE, BigDecimal.class))).multiply(new BigDecimal("10000"));
        orderMapper.updateByPrimaryKeySelective(new Order(a -> {
            a.setId(order.getId());
            //点买成交价格
            a.setBuyDealPrice(order.getBuyDealPrice());
            a.setBuyDealNumber(order.getBuyDealNumber());
            a.setStatus(Order.STATUS.T3.code);
            a.setBuyDealTime(DateUtils.getNow());
            a.setDepositProfit(profitDeposit);
        }));

        //投资人账户记录
        Invest invest = investMapper.selectOne(new Invest(v -> {
            v.setUserId(order.getInvestorId());
        }));

        //投资人账户
        Account account = accountMapper.selectByUID(invest.getUserId());
        if (account == null) {
            throw new BussinessException("账户不存在");
        } else {
            if (account.getAvailable().subtract(profitDeposit).compareTo(BigDecimal.ZERO) < 0) {
                throw new BussinessException("可用余额不足");
            } else {
                AccountLog accountLog = AccountLog.buildLog(invest.getUserId(), order.getId(), profitDeposit, AccountLog.TYPE.T13, account, "抢单交易冻结止盈保证金" + profitDeposit + "元");
                if (accountLogService.insert(accountLog) != 1) {
                    throw new BussinessException("抢单交易冻结止盈保证金失败");
                }
                if (accountMapper.updateAccount(BigDecimal.ZERO, BigDecimal.ZERO, profitDeposit.negate(), profitDeposit, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, invest.getUserId()) != 1) {
                    throw new BussinessException("抢单交易冻结止盈保证金失败");
                }
            }
        }
        //股票账户的资金变动
        BigDecimal total = new BigDecimal(order.getBuyDealNumber()).multiply(order.getBuyDealPrice());
        //校验余额是否够
        if (invest.getInvestAccount().subtract(total).compareTo(BigDecimal.ZERO) < 0) {
            throw new BussinessException("余额不足");
        }

        investAccountLogMapper.insert(new InvestAccountLog(t -> {
            t.setOrderId(order.getId());
            t.setInvestId(invest.getId());
            t.setUserId(invest.getUserId());
            t.setDirection(InvestAccountLog.DIRECTION.T1.code);
            t.setDealNumber(order.getBuyDealNumber());
            t.setDealPrice(order.getBuyDealPrice());
            t.setDealAmount(total);
            t.setAmount(total);
            t.setAcocuntLeft(invest.getInvestAccount().subtract(total));
            t.setCode(order.getEquityCode());
            t.setName(order.getEquityName());
            t.setRemark("买入股票");
        }));
        //投资人表更新抢单数和用户余额
        investMapper.updateByPrimaryKeySelective(new Invest(t -> {
            t.setId(invest.getId());
            t.setReceiveCount(invest.getReceiveCount() + 1);
            t.setInvestAccount(invest.getInvestAccount().subtract(total));
        }));

        //平台添加综合管理费,次销售获取佣金
        doPaidFee(order);
//            代理商分佣
//            doAgentFee(ord);
//            //分配销售销售佣金
//            doSellerFee(ord);
        String operation = "订单ID: 【 " + order.getId() + " 】, " + "点买成交价格：【 " + order.getBuyDealPrice() + " 】元 " + "点买数量：【 " + order.getBuyDealNumber() + " 】";
        orderOperationService.saveOrderOperationAdmin(order, operation, admin);

    }


    @Override
    public List<Order> selectOrderForTime(Map<String, Object> param) {
        return orderMapper.findOrderForTime(param);
    }

    @Override
    public void buyOrder(User user, ModelRealTime modelRealTime, BuyModel model) {
        //保存订单信息
        String orderNo = OrderNoUtils.getSerialNumber();
        orderMapper.insert(new Order(t -> {
            t.setUserId(user.getId());
            t.setOrderNo(orderNo);
            t.setType(Order.TYPE.T1.code);
            t.setEquityCode(modelRealTime.getStock_code());
            t.setEquityName(modelRealTime.getCode_name());
            t.setDivideScale(model.getDivideScale());
            t.setUseRatio(model.getUseRatio());
            t.setDeposit(model.getDeposit());
            t.setProfitStopPrice(model.getProfitStopPrice());
            t.setLoseStopPrice(model.getLoseStopPrice());
            t.setPaidFee(model.getPaidFee());
            t.setBuyPrice(new BigDecimal(modelRealTime.getLast_price()));
            //建仓收取的管理费
            t.setPaidFeeBuy(model.getPaidFee());
            t.setPaidDiyan(BigDecimal.ZERO);
            t.setUnpaidDiyan(BigDecimal.ZERO);
            t.setBuyNumber(model.getBuyNumber());
            t.setTradeCredit(model.getTradeCredit());
            t.setBuyTime(DateUtils.getNow());
            t.setLossLimit(model.getLossLimit());
            t.setLossRate(model.getLossRate());
            t.setStatus(Order.STATUS.T1.code);
            t.setDiyanTime(0);
            if (StringUtils.isNotBlank(user.getInviteId())) {
                t.setInviterId(user.getInviteId());
            }
        }));
        Order order = orderMapper.selectByOrderNo(orderNo);
        String operation = "发起点买，客户ID：【 " + user.getId() + " 】, " + "股票代码 ：【 " + modelRealTime.getStock_code() + " 】, " + "股票名称：【 " + modelRealTime.getCode_name() + " 】, " + "点买额度 ：【 " + model.getTradeCredit() + " 】 万元, " + "可买股数 ：【 " + model.getBuyNumber() + " 】 股, ";
        // 保存订单操作日志
        orderOperationService.saveOrderOperation(order, operation);

        //冻结履约保证金， 扣除综合费
        Account account = accountMapper.selectByUID(user.getId());

        //记录资金记录
        //冻结履约保证金
        AccountLog accountLog1 = AccountLog.buildLog(user.getId(), order.getId(), model.getDeposit(), AccountLog.TYPE.T10, account, "点买交易冻结履约保证金" + model.getDeposit() + "元");
        if (accountLogMapper.insert(accountLog1) != 1) {
            throw new BussinessException("点买交易冻结履约保证金失败");
        }

        //扣除综合管理费 TODO 目前，履约保证金和综合管理费都是冻结的处理
        AccountLog accountLog2 = AccountLog.buildLog(user.getId(), order.getId(), model.getPaidFee(), AccountLog.TYPE.T11, account, "点买交易扣除综合管理费" + model.getPaidFee() + "元");
        if (accountLogMapper.insert(accountLog2) != 1) {
            throw new BussinessException("点买交易扣除综合管理费失败");
        }

        //更新资金(-综合管理费，-履约保证金-综合管理费，+履约保证金)
        int i = accountMapper.updateAccount(model.getPaidFee().negate(), BigDecimal.ZERO, model.getDeposit().add(model.getPaidFee()).negate(),
                                            model.getDeposit(), BigDecimal.ZERO, model.getPaidFee(), BigDecimal.ZERO, user.getId());
        /**
         * @param total          总额变化量
         * @param moneyAvailable 钱包金额变化量
         * @param available      可用变化量
         * @param freeze         冻结变化量
         * @param tenderCount    点买总额变化量
         * @param feeCount       费用总额变化量
         * @param profitCount    盈利总额变化量
         * @param userId         用户ID
         */
        if (i != 1) {
            throw new BussinessException("更新账户资金失败");
        }
    }

    @Override
    public void toCover(Integer id, User user) throws Exception {
        Order order = orderMapper.selectByPrimaryKey(id);
        if (null == order) {
            throw new BussinessException("订单不存在");
        }
        if (user.getId() != order.getUserId()) {
            throw new BussinessException("您无权操作该订单");
        }
        //判断是否在交易时段
        Integer isOpenTradeTime = redisService.get(ConfigNID.IS_OPEN_TRADE_TIME, Integer.class);
        if (null == isOpenTradeTime || isOpenTradeTime == 1) {
            if (!OrderModel.checkTradeDate()) {
                new BussinessException("非交易时间");
            }
        }
        //判断是否是单日的订单
        if (DateUtils.secondBetween(DateUtils.getTodayZero(), order.getBuyTime()) > 0) {
            //当天订单，不能点卖
            throw new BussinessException("当天订单不能平仓");
        }
        //判断是否是交易中
        if (order.getStatus() != Order.STATUS.T3.code) {
            throw new BussinessException("订单状态已更改，请刷新");
        }
        orderMapper.updateByPrimaryKeySelective(new Order(t -> {
            t.setId(order.getId());
            t.setStatus(Order.STATUS.T5.code);
            t.setPingcangType(Order.PINGCANGTYPE.T1.code);
            t.setEveningUpTime(DateUtils.getNow());
        }));
        String operation = "订单ID：【 " + order.getId() + " 】 于 " + DateUtils.dateStr4(new Date()) + " 由 【 " + user.getUserName() + " 】 " + " 发起平仓申请 ";
        orderOperationService.saveOrderOperation(order, operation);
    }

    /**
     * 平台获取综合管理费，及次销售获取佣金
     */
    private void doPaidFee(Order order) throws Exception {
        //平台收取综合管理费
        BigDecimal paidFee = order.getPaidFee();
        Account pAccount = accountMapper.selectByUID(1);
        //资金日志(平台账户)
        AccountLog accountLog = AccountLog.buildLog(1, order.getId(), paidFee, AccountLog.TYPE.T19, pAccount, "点买交易平台收取综合管理费" + paidFee + "元");
        if (accountLogMapper.insert(accountLog) != 1) {
            throw new BussinessException("点买交易平台收取综合管理费失败");
        }
        //记录平台资金日志
        platAccountLogService.generateLog(pAccount.getAvailable(), paidFee, Enum.Direction.IN, Constant.ACCOUNT_TYPE.MANAGEFEE);
        //更新平台账户
        if (accountMapper.updateAccount(paidFee, BigDecimal.ZERO, paidFee, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, 1) != 1) {
            throw new BussinessException("点买交易平台收取综合管理费失败");
        }
    }

    @Override
    public long countOrders(int id) {
        List count = orderMapper.select(new Order(a -> {
            a.setUserId(id);
        }));
        return count.size();
    }

    @Override
    public long getTotalClosingCount(Admin currAdmin) {
        List count = orderMapper.select(new Order(a -> {
            a.setInvestorId(currAdmin.getUserId());
            a.setStatus(Order.STATUS.T5.code);
            a.setDelFlag(Order.DELFLAG.NORMAL.code);
        }));
        return count.size();
    }


    @Override
    public int doScrambleOrder(Order order, Admin admin) throws Exception {
        Invest invest = investMapper.selectOne(new Invest(v -> {
            v.setUserId(admin.getUserId());
        }));
        if (null == invest) {
            throw new BussinessException("投资人身份错误");
        }
        //判断投资人余额是否充足
        BigDecimal total = order.getBuyPrice().multiply(new BigDecimal(order.getBuyNumber()));
        if (invest.getInvestAccount().subtract(total).compareTo(BigDecimal.ZERO) < 0) {
            throw new BussinessException("股票账户余额不足");
        }

        if (!Objects.equals(order.getStatus(), Enum.OrderStatus.MATCHING.getValue())) {
            throw new BussinessException("订单状态已改变");
        } else {
            //更新操作日志
            String operation = "订单ID: 【 " + order.getId() + " 】, 于 " + DateUtils.dateStr4(new Date()) + " 由投资人:【 " + admin.getName() + " 】 接单 ";
            orderOperationService.saveOrderOperationAdmin(order, operation, admin);
            return orderMapper.updateByPrimaryKeySelective(new Order(v -> {
                v.setInvestorId(invest.getUserId());
                v.setAcceptTime(DateUtils.getNow());
                v.setStatus(Order.STATUS.T2.code);
                v.setId(order.getId());
                v.setUserId(order.getUserId());
            }));
        }
    }

    /**
     * 修改持仓中的订单信息
     *
     * @param orderId          订单id
     * @param modifyDealPrice  修改后金额
     * @param modifyDealNumber 修改后数量
     * @param name
     * @return
     * @throws Exception
     */
    @Override
    public int modifyHoldingOrder(Integer orderId, Double modifyDealPrice, Integer modifyDealNumber, String name) throws Exception {
        Order order = orderMapper.selectByPrimaryKey(orderId);
        if (order == null) {
            throw new BussinessException("订单为空");
        }
        String desc = "买入成交价格由[" + order.getBuyDealPrice() + "]修改为[" + modifyDealPrice + "],买入成交股数由[" + order.getBuyDealNumber() + "]修改为[" + modifyDealNumber + "]";
        String remark = "持仓中订单修改信息(" + order.getBuyDealPrice() + " -> " + modifyDealPrice + "," + order.getBuyDealNumber() + " -> " + modifyDealNumber + ")";
        order.setBuyDealNumber(modifyDealNumber);
        order.setBuyDealPrice(new BigDecimal(modifyDealPrice));
        //结算
        orderMapper.updateByPrimaryKeySelective(order);
        //记录操作
        int operation = orderOperationService.insert(new OrderOperation(a -> {
            a.setOrderId(orderId);
            a.setOperation(desc);
            a.setOperationTime(DateUtils.getNow());
            a.setRemark(remark);
            a.setDelFlag(OrderOperation.DELFLAG.NORMAL.code);
            a.setCreateTime(DateUtils.getNow());
            a.setUpdator(name);
            a.setCreator(name);
        }));
        if (operation < 0) {
            throw new BussinessException("参数错误");
        }
        return operation;
    }


    /**
     * 投资人资金操作
     *
     * @param o             订单
     * @param depositProfit 保证金
     * @param amount        操作金额
     * @param ac            账户
     * @throws Exception
     */
    @Override
    public void doInvestAccountOperation(Order o, BigDecimal depositProfit, BigDecimal amount, Account ac, Integer type) throws Exception {
        if (type == 1) {
            //资金记录 解冻止盈保证金 - 点买人盈利资金
            AccountLog accountLog3 = AccountLog.buildLog(ac.getUserId(), o.getId(), depositProfit, AccountLog.TYPE.T14, ac, "订单盈利解冻止盈保证金：" + depositProfit + "元");
            if (accountLogMapper.insert(accountLog3) != 1) {
                throw new BussinessException("订单盈利解冻投资人止盈保证金失败");
            }

            AccountLog accountLog4 = AccountLog.buildLog(ac.getUserId(), o.getId(), amount, AccountLog.TYPE.T15, ac, "订单盈利投资人扣除点买盈利资金：" + amount + "元");
            if (accountLogMapper.insert(accountLog4) != 1) {
                throw new BussinessException("订单盈利扣除投资人点买盈利资金失败");
            }

            //投资人 解冻止盈保证金 - 点买人盈利资金
            if (accountMapper.updateAccount(amount.negate(), BigDecimal.ZERO, depositProfit.subtract(amount), depositProfit.negate(), BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, o.getInvestorId()) != 1) {
                throw new BussinessException("扣除投资人资金失败");
            }
        } else if (type == 2) {
            //资金记录 解冻止盈保证金 +点买人亏损资金
            AccountLog accountLog3 = AccountLog.buildLog(ac.getUserId(), o.getId(), depositProfit, AccountLog.TYPE.T14, ac, "订单亏损解冻止盈保证金：" + depositProfit + "元");
            if (accountLogMapper.insert(accountLog3) != 1) {
                throw new BussinessException("订单亏损解冻止盈保证金失败");
            }

            AccountLog accountLog4 = AccountLog.buildLog(ac.getUserId(), o.getId(), amount, AccountLog.TYPE.T15, ac, "订单亏损投资人获取点买亏损资金：" + amount + "元");
            if (accountLogMapper.insert(accountLog4) != 1) {
                throw new BussinessException("订单亏损投资人获取点买亏损资金失败");
            }

            //投资人 解冻止盈保证金 +点买人亏损资金
            if (accountMapper.updateAccount(amount, BigDecimal.ZERO, depositProfit.add(amount), depositProfit.negate(), BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, o.getInvestorId()) != 1) {
                throw new BussinessException("解冻止盈保证金和获取点买人亏损资金失败");
            }
        } else if (type == 3) {
            //资金记录 解冻止盈保证金 +点买人亏损资金
            AccountLog accountLog3 = AccountLog.buildLog(ac.getUserId(), o.getId(), depositProfit, AccountLog.TYPE.T14, ac, "订单亏损(穿仓)解冻止盈保证金：" + depositProfit + "元");
            if (accountLogMapper.insert(accountLog3) != 1) {
                throw new BussinessException("订单亏损(穿仓)解冻止盈保证金失败");
            }

            AccountLog accountLog4 = AccountLog.buildLog(ac.getUserId(), o.getId(), amount, AccountLog.TYPE.T15, ac, "订单亏损(穿仓)投资人获取点买亏损资金：" + amount + "元");
            if (accountLogMapper.insert(accountLog4) != 1) {
                throw new BussinessException("订单亏损(穿仓)投资人获取点买亏损资金失败");
            }

            //投资人 解冻止盈保证金 +点买人亏损资金
            if (accountMapper.updateAccount(amount, BigDecimal.ZERO, depositProfit.add(amount), depositProfit.negate(), BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, o.getInvestorId()) != 1) {
                throw new BussinessException("解冻止盈保证金和获取点买人亏损资金失败");
            }
        }
        //佣金 = 买入成交价格 * 数量 *佣金比例
        Invest invest1 = investMapper.selectOne(new Invest(t -> {
            t.setUserId(o.getInvestorId());
        }));

        if (null != invest1) {
            //佣金 = 买入成交价格 * 数量 *佣金比例
            BigDecimal scale = invest1.getFeeScale();
            //股票卖出成交价格*数量
            BigDecimal deal = o.getSellDealPrice().multiply(BigDecimal.valueOf(o.getSellDealNumber()));
            BigDecimal brokerage = scale.multiply(deal);
            if (PriceHelper.isLessThan(brokerage, new BigDecimal("5"))) {
                brokerage = BigDecimal.valueOf(5);
            }
            //佣金双向收费 *2
            BigDecimal totalBrokerage = BigDecimal.valueOf(2).multiply(brokerage);
            //印花税 比例
            BigDecimal yinhuaScale = redisService.get(ConfigNID.FEE_YINHUA, BigDecimal.class);
            //印花税
            BigDecimal feeYinhua = yinhuaScale.multiply(deal);
            //投资者账户余额 + 股票卖出成交价格*数量 - 佣金 -印花税
            BigDecimal investAccout = deal.subtract(totalBrokerage).subtract(feeYinhua);
            invest1.setInvestAccount(invest1.getInvestAccount().add(investAccout));
            investMapper.updateByPrimaryKeySelective(invest1);

            investAccountLogMapper.insert(new InvestAccountLog(t -> {
                t.setOrderId(o.getId());
                t.setInvestId(invest1.getId());
                t.setUserId(invest1.getUserId());
                t.setDirection((int) Enum.Direction.IN.getValue());
                t.setDealNumber(o.getSellDealNumber());
                t.setDealPrice(o.getSellDealPrice());
                //佣金
                t.setFeeTrade(totalBrokerage);
                //印花税
                t.setTaxYinhua(feeYinhua);
                t.setDealAmount(deal);
                t.setAmount(investAccout);
                t.setAcocuntLeft(invest1.getInvestAccount());
                t.setCode(o.getEquityCode());
                t.setName(o.getEquityName());
                t.setRemark("卖出股票");
                t.setCreateTime(new Timestamp(new Date().getTime()));
            }));
        }
    }

    @Override
    public DtGrid getDtGridListForDiyan(String dtGridPager, Class entityClazz) throws DtGridException {
        try {
            ObjectMapper mapper = new ObjectMapper();
            HashMap<String, String> hashMap = new HashMap<>();
            DtGrid dtGrid = mapper.readValue(dtGridPager, DtGrid.class);
            if (dtGrid.getNcColumnsType() != null && dtGrid.getNcColumnsType().size() > 0) {
                for (String key : dtGrid.getNcColumnsType().keySet()) {
                    for (int i = 0; i < dtGrid.getNcColumnsType().get(key).size(); i++) {
                        hashMap.put((String) dtGrid.getNcColumnsType().get(key).get(i), key);
                    }
                    dtGrid.setNcColumnsTypeList(hashMap);
                }
            }
            // 表格查询参数处理
            QueryUtils.parseDtGridSql(dtGrid);
            // 获取查询条件Sql
            String whereSql = dtGrid.getWhereSql();
            // 获取排序Sql
            String sortSql = dtGrid.getSortSql();

            Map<String, Object> params = new HashMap<>();
            params.put("whereSql", whereSql);
            params.put("sortSql", sortSql);
            Integer recordCount = orderMapper.findCountDtGridDiYanGroupByUser(params);
            if (null == recordCount) {
                recordCount = 0;
            }
            int pageSize = dtGrid.getPageSize();
            int pageNum = recordCount / dtGrid.getPageSize() + (recordCount % dtGrid.getPageSize() > 0 ? 1 : 0);

            dtGrid.setPageCount(pageNum);
            dtGrid.setRecordCount(recordCount);

            params.put("nowPage", (dtGrid.getNowPage() - 1) * pageSize);
            params.put("pageSize", pageSize);

            List<OrderModel> list = orderMapper.findListDtGridDiYanGroupByUser(params);
            dtGrid.setExhibitDatas(JsonUtils.toGenericObject(JSON.toJSONString(list), new TypeReference<List<Object>>() {
            }));
            return dtGrid;
        } catch (Exception e) {
            e.printStackTrace();
            throw new DtGridException();
        }
    }

    /**
     * 订单补亏
     *
     * @param order
     * @param repair
     * @param admin
     * @throws Exception
     */

    @Override
    public void doRepairLoss(Order order, BigDecimal repair, Admin admin) throws Exception {
//        //递延阈值
//        String diyanLimit = redisService.get(ConfigNID.DIYAN_LIMIT);
//        //补亏 ，增加履约保证金，增加止损金额
//        BigDecimal depositBefore = order.getDeposit();
//        BigDecimal stopLossBefore = order.getStopLossLine();
//        BigDecimal lossLimitBefore = order.getLossLimit();
//
//        order.setDeposit(order.getDeposit().add(repair));
//        order.setStopLossLine(order.getStopLossLine().subtract(repair));
//        order.setLossLimit(order.getDeposit().subtract(new BigDecimal(diyanLimit).multiply(order.getTradeCredit().multiply(new BigDecimal("10000")))).negate());
//        //补亏资金记录
//        doRepairLog(order, repair);
//        //增加履约保证金，增加止损金额
//        orderMapper.updateByPrimaryKeySelective(order);
//        BigDecimal depositAfter = order.getDeposit();
//        BigDecimal stopLossAfter = order.getStopLossLine();
//        BigDecimal lossLimitAfter = order.getLossLimit();
//        //记录订单操作日志
//        String operation = "补亏金额" + " 【 " + repair + " 】 元, " + "补亏前履约保证金: " + depositBefore + " 元," + "补亏后履约保证金: " + depositAfter + " 元," + "补亏前止损线: " + stopLossBefore + " 元，" + "补亏后止损线: " + stopLossAfter + " 元，" + " 补亏前递延条件：" + lossLimitBefore + " 元 " + "补亏后递延条件: " + lossLimitAfter + " 元";
//        orderOperationService.saveOrderOperationAdmin(order, operation, admin);
    }

    /**
     * 补亏资金记录
     *
     * @param order
     * @param repair
     * @throws Exception
     */
    @Override
    public void doRepairLog(Order order, BigDecimal repair) throws Exception {
        Account account = accountMapper.selectOne(new Account(a -> {
            a.setUserId(order.getUserId());
            a.setDelFlag(Order.DELFLAG.NORMAL.code);
        }));
        if (null != account) {
            //判断余额是否充足
            if (account.getAvailable().compareTo(repair) < 0) {
                throw new BussinessException("可用余额不足");
            }
            //修改可用金额和冻结金额
            if (accountMapper.updateAccount(BigDecimal.ZERO, BigDecimal.ZERO, repair.negate(), repair, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, order.getUserId()) != 1) {
                throw new BussinessException("修改可用金额和冻结金额失败");
            }

            //手动补亏增加资金记录
            AccountLog accountLog = AccountLog.buildLog(order.getUserId(), order.getId(), repair, AccountLog.TYPE.T20, account, "手动补亏" + repair + "元");
            if (accountLogMapper.insert(accountLog) != 1) {
                throw new BussinessException("手动补亏失败");
            }
        }
    }

    /**
     * 结算
     *
     * @param order 订单
     * @param admin
     * @throws Exception
     */
    @Override
    public synchronized void doAccount(Order order, Admin admin) throws Exception {
        Order o = orderMapper.selectByPrimaryKey(order.getId());
        if (null == o) {
            throw new BussinessException("订单不存在");
        }
        if (o.getStatus() != Order.STATUS.T6.code && o.getStatus() != Order.STATUS.T7.code) {
            throw new BussinessException("订单状态已改变");
        }
        //盈利分成比例
        BigDecimal divideScale = o.getDivideScale();
        //履约保证金
        BigDecimal deposit = o.getDeposit();
        //止盈保证金
        BigDecimal depositProfit = o.getDepositProfit();
        //计算盈亏
        //买入成交价
        BigDecimal buyDealprice = order.getBuyDealPrice();
        //买入成交数
        BigDecimal buyDealNum = new BigDecimal(order.getBuyDealNumber());
        //卖出成交价
        BigDecimal sellDealPrice = order.getSellDealPrice();
        //卖出成交数
        Integer sellDealNum = order.getSellDealNumber();
        //买入总金额
        BigDecimal buyTotal = buyDealprice.multiply(buyDealNum);
        //卖出总金额
        BigDecimal sellTotal = sellDealPrice.multiply(BigDecimal.valueOf(sellDealNum));
        //计算卖出总金额和买入总金额的差价
        BigDecimal account = sellTotal.subtract(buyTotal);
        //更新order表信息的

        orderMapper.updateByPrimaryKeySelective(new Order(a -> {
            a.setId(order.getId());
            a.setSellDealPrice(order.getSellDealPrice());
            a.setSellDealNumber(order.getSellDealNumber());
            a.setBuyDealNumber(order.getBuyDealNumber());
            a.setBuyDealPrice(order.getBuyDealPrice());
            a.setStatus(Order.STATUS.T7.code);
            a.setSettleTime(DateUtils.getNow());
            a.setProfitCount(account);
        }));


        Account ac = accountMapper.selectOne(new Account(a -> {
            a.setUserId(o.getUserId());
            a.setDelFlag(Account.DELFLAG.NORMAL.code);
        }));

        Account invest = accountMapper.selectOne(new Account(v -> {
            v.setUserId(o.getInvestorId());
            v.setDelFlag(Account.DELFLAG.NORMAL.code);
        }));
        //盈利
        if (PriceHelper.isGreaterThan(account, BigDecimal.ZERO)) {
            //点买人盈利资金
            BigDecimal buyProfit = account.multiply(divideScale);
            //资金记录 解冻履约保证金 ,盈利资金
            AccountLog accountLog1 = AccountLog.buildLog(ac.getUserId(), o.getId(), o.getDeposit(), AccountLog.TYPE.T14, ac, "订单盈利解冻履约保证金：" + o.getDeposit() + "元");
            if (accountLogMapper.insert(accountLog1) != 1) {
                throw new BussinessException("订单盈利解冻履约保证金失败");
            }

            AccountLog accountLog2 = AccountLog.buildLog(ac.getUserId(), o.getId(), buyProfit, AccountLog.TYPE.T15, ac, "订单盈利金额：" + buyProfit + "元");
            if (accountLogMapper.insert(accountLog2) != 2) {
                throw new BussinessException("订单盈利金额添加失败");
            }

            //点买人 账户 + 解冻履约保证金 + 盈利资金
            if (accountMapper.updateAccount(buyProfit, BigDecimal.ZERO, buyProfit.add(deposit), deposit.negate(), o.getTradeCredit(), BigDecimal.ZERO, buyProfit, o.getUserId()) != 1) {
                throw new BussinessException("点买人更新账户失败");
            }

            //投资人资金记录 账户修改 ，修改投资人账户
            doInvestAccountOperation(o, depositProfit, buyProfit, invest, 1);
        } else {
            //计算亏损
            if (PriceHelper.isGreaterThan(deposit, account.negate())) {
                //亏损少于履约保证金
                //计算履约保证金 - 亏损值
                BigDecimal buyLoss = deposit.add(account);

                //资金记录 解冻履约保证金 ,亏损资金
                AccountLog accountLog1 = AccountLog.buildLog(ac.getUserId(), o.getId(), o.getDeposit(), AccountLog.TYPE.T14, ac, "订单亏损解冻履约保证金：" + o.getDeposit() + "元");
                if (accountLogMapper.insert(accountLog1) != 1) {
                    throw new BussinessException("订单亏损解冻履约保证金失败");
                }

                AccountLog accountLog2 = AccountLog.buildLog(ac.getUserId(), o.getId(), buyLoss, AccountLog.TYPE.T16, ac, "订单亏损金额：" + buyLoss + "元");
                if (accountLogMapper.insert(accountLog2) != 1) {
                    throw new BussinessException("订单亏损金额操作失败");
                }

                //点买人 账户 + 解冻履约保证金 -亏损资金
                if (accountMapper.updateAccount(account, BigDecimal.ZERO, buyLoss, deposit.negate(), o.getTradeCredit(), BigDecimal.ZERO, account, o.getUserId()) != 1) {
                    throw new BussinessException("点买人账户更新失败");
                }

                //投资人
                doInvestAccountOperation(o, depositProfit, account, invest, 2);
            } else {
                //亏岁大于履约保证金（穿仓）
                //用户
                //资金记录 解冻履约保证金 ,亏损资金
                AccountLog accountLog1 = AccountLog.buildLog(ac.getUserId(), o.getId(), o.getDeposit(), AccountLog.TYPE.T14, ac, "订单亏损(穿仓)解冻履约保证金：" + o.getDeposit() + "元");
                if (accountLogMapper.insert(accountLog1) != 1) {
                    throw new BussinessException("订单亏损(穿仓)解冻履约保证金失败");
                }

                AccountLog accountLog2 = AccountLog.buildLog(ac.getUserId(), o.getId(), o.getDeposit(), AccountLog.TYPE.T16, ac, "订单亏损金额：" + o.getDeposit() + "元");
                if (accountLogMapper.insert(accountLog2) != 1) {
                    throw new BussinessException("订单亏损金额添加失败");
                }

                //点买人 账户 + 解冻履约保证金 -亏损资金（履约保证金）
                if (accountMapper.updateAccount(deposit.negate(), BigDecimal.ZERO, BigDecimal.ZERO, deposit.negate(), o.getTradeCredit(), BigDecimal.ZERO, deposit.negate(), o.getUserId()) != 1) {
                    throw new BussinessException("点买人账户解冻履约保证金及扣除亏损资金失败");
                }

                //投资人
                doInvestAccountOperation(o, depositProfit, deposit, invest, 3);
            }
        }
        String operation = "订单ID：【 " + o.getId() + " 】 于 " + DateUtils.dateStr4(new Date()) + " 由 【 " + admin.getName() + " 】 " + " 审核成功, " + " 卖出价格：【 " + o.getSellDealPrice() + " 】 " + " 卖出数量：【 " + o.getSellDealNumber() + " 】 ";
        orderOperationService.saveOrderOperationAdmin(o, operation, admin);
    }

    @Override
    public List<OrderModel> selectDiYanGroupByUser() {
        return orderMapper.findDiYanGroupByUser(Order.STATUS.T3.code);
    }

    @Override
    public void doCoverOrder(Integer orderId, Integer coverType) throws Exception {
        Order order = orderMapper.selectByPrimaryKey(orderId);
        if (null != order) {
            if (order.getStatus().equals(Order.STATUS.T3.code)) {
                orderMapper.updateByPrimaryKeySelective(new Order(t -> {
                    t.setId(order.getId());
                    t.setStatus(Order.STATUS.T5.code);
                    t.setPingcangType(coverType);
                    t.setEveningUpTime(DateUtils.getNow());
                }));

                ModelRealTime model = QuotationEndpoint.realtime(order.getEquityCode());
                if (model != null) {
                    String operation = "";
                    if (coverType == Order.PINGCANGTYPE.T2.code) {
                        operation = "订单ID：【 " + order.getId() + " 】 于 " + DateUtils.dateStr4(new Date()) + "  因：【触发止损条件】 由 持仓中改为平仓 " + "股票价格为：【" + model.getLast_price() + " 】";

                    }
                    orderOperationService.saveOrderOperation(order, operation);
                }
            }
        }
    }

    @Override
    public void doFlowOrder(Integer orderId, Admin admin) throws Exception {
        String flowTime = redisService.get(ConfigNID.ORDER_EXSIT_TIME);
        Order order = orderMapper.selectByPrimaryKey(orderId);
        if (null != order) {
            if (order.getStatus().equals(Order.STATUS.T2.code)) {
                orderMapper.updateByPrimaryKeySelective(new Order(t -> {
                    t.setId(order.getId());
                    t.setStatus(Order.STATUS.T8.code);
                }));
                String operation;
                if (null != admin) {
                    operation = "订单ID: 【 " + order.getId() + " 】,  于 " + DateUtils.dateStr4(new Date()) + " 由 : 【" + admin.getName() + " 】" + " 流单 ";
                } else {
                    operation = "订单ID：【 " + order.getId() + " 】 于 " + DateUtils.dateStr4(new Date()) + "  因：【 " + flowTime + "s无人接单】 流单 ";
                }
                orderOperationService.saveOrderOperation(order, operation);

                //退还履约保证金，综合管理费
                Account account = accountMapper.selectByUID(order.getUserId());

                //记录资金记录
                //解冻履约保证金
                AccountLog accountLog1 = AccountLog.buildLog(order.getUserId(), order.getId(), order.getDeposit(), AccountLog.TYPE.T14, account, "点买交易流单解冻履约保证金" + order.getDeposit() + "元");
                if (accountLogService.insert(accountLog1) != 1) {
                    throw new BussinessException("点买交易流单解冻履约保证金失败");
                }

                //返还综合管理费
                AccountLog accountLog2 = AccountLog.buildLog(order.getUserId(), order.getId(), order.getPaidFee(), AccountLog.TYPE.T24, account, "点买交易流单返还综合管理费" + order.getPaidFee() + "元");
                if (accountLogService.insert(accountLog2) != 1) {
                    throw new BussinessException("点买交易流单返还综合管理费失败");
                }

                //更新账户(+管理费，+管理费+履约保证金，-履约保证金)
                if (accountMapper.updateAccount(order.getPaidFee(), BigDecimal.ZERO, order.getDeposit().add(order.getPaidFee()), order.getDeposit().negate(), BigDecimal.ZERO, order.getPaidFee().negate(), BigDecimal.ZERO, order.getUserId()) != 1) {
                    throw new BussinessException("更新账户失败");
                }

            }
        }
    }

    @Override
    public void doSell(Order order, Admin admin) throws Exception {
        orderMapper.updateByPrimaryKeySelective(new Order(t -> {
            t.setId(order.getId());
            t.setStatus(Order.STATUS.T5.code);
            t.setPingcangType(Constant.ClosePositionType.FORCE.getValue());
            t.setEveningUpTime(DateUtils.getNow());
        }));
        String operation = "订单ID: 【 " + order.getId() + " 】 于 " + new Date() + " 由 【 " + admin.getName() + " 】 " + " 发起强制平仓 ";
        orderOperationService.saveOrderOperationAdmin(order, operation, admin);
    }

    @Override
    public void doBackWithCoving(Order order, Admin admin) throws Exception {
        orderMapper.updateByPrimaryKeySelective(new Order(t -> {
            t.setId(order.getId());
            t.setStatus(Order.STATUS.T3.code);
        }));
        String operation = "订单ID：【 " + order.getId() + " 】 于 " + DateUtils.dateStr4(new Date()) + " 由 【 " + admin.getName() + " 】 " + " 从【平仓】 撤回到 【持仓中】 ";
        orderOperationService.saveOrderOperationAdmin(order, operation, admin);
    }

    @Override
    public void doSaleBack(Order order, Admin admin) throws Exception {
        Order or = selectByPrimaryKey(order.getId());
        if (null != or) {
            if (or.getStatus() != Order.STATUS.T5.code) {
                throw new BussinessException("当前订单状态不能点卖回填或已点卖回填");
            }
            if (order.getSellDealNumber() > Integer.parseInt(String.valueOf(or.getBuyDealNumber()))) {
                throw new BussinessException("卖出数量不能大于买入数量！");
            }
            or.setSellDealNumber(order.getSellDealNumber());
            or.setSellDealPrice(order.getSellDealPrice());
            or.setSellDealTime(DateUtils.getNow());
            or.setStatus(Order.STATUS.T6.code);
            updateByPrimaryKeySelective(or);
            String operation = "订单ID：【 " + order.getId() + " 】 于 " + DateUtils.dateStr4(new Date()) + " 由 【 " + admin.getName() + " 】 " + " 卖出成功, " + " 卖出价格：【 " + order.getSellDealPrice() + " 】 " + " 卖出数量：【 " + order.getSellDealNumber() + " 】 ";
            orderOperationService.saveOrderOperationAdmin(or, operation, admin);
            //极光推送发送通知
//            JPushClientUtil.sendToAliasId(String.valueOf(or.getUserId()), "您有一笔订单卖出成功！", "", "", "");
        } else {
            throw new BussinessException("参数有误");
        }
    }

    @Override
    public Map<Integer, List<Order>> splitGroupByUser(List<Order> list) {
        Map<Integer, List<Order>> map = new HashMap<>();
        for (Order order : list) {
            if (map.containsKey(order.getUserId())) {
                List<Order> items = map.get(order.getUserId());
                items.add(order);
                map.put(order.getUserId(), items);
            } else {
                List<Order> items = new ArrayList<>();
                items.add(order);
                map.put(order.getUserId(), items);
            }
        }
        return map;
    }

    @Override
    public BigDecimal getTotalDeferMoney(List<Order> waitDeferOrders) {
        //每万元递延费
        BigDecimal perTenThousandDeferFee = redisService.get(ConfigNID.DIYAN_FEE, BigDecimal.class);
//        Integer totalTradeCredit = 0;
        double totalUnPaid = 0;
        for (Order order : waitDeferOrders) {
            order.setUnpaidDiyan(order.getUnpaidDiyan().add(perTenThousandDeferFee.multiply(order.getTradeCredit())));
            //总点买额度
//            totalTradeCredit += order.getTradeCredit();
            //用户该订单欠的递延费
            totalUnPaid += order.getUnpaidDiyan().doubleValue();
        }
//        BigDecimal decimal = perTenThousandDeferFee.multiply(new BigDecimal(totalTradeCredit));
//        return decimal.add(new BigDecimal(totalUnPaid));
        return new BigDecimal(totalUnPaid);
    }

    @Override
    public Order getMinTradeCreditOrMaxProfitOrder(List<Order> orders) {
        if (CollectionUtils.isEmpty(orders)) {
            return null;
        } else {
            //因为该订单集合本身就是按照金额最小升序排列的。  这里只需要取第一条订单的点买金额 ，如果该点买金额只有一条 则直接返回，
            //如果有多条 则计算与该点买金额相同的订单的收益，取收益最大的返回。
            if (orders.size() > 1) {
                BigDecimal firstTradeCredit;
                List<Order> tempOrders = new ArrayList<>();
                //第一条小于第二条，直接返回第一条
                if (orders.get(0).getTradeCredit().compareTo(orders.get(1).getTradeCredit()) == -1) {
                    return orders.get(0);
                } else {
                    //第一条不小于第二条，则查询与第一条点买金额相同的订单，并放入缓存集合
                    firstTradeCredit = orders.get(0).getTradeCredit();
                    tempOrders.add(orders.get(0));
                    for (int i = 1; i < orders.size(); i++) {
                        if (orders.get(i).getTradeCredit() == firstTradeCredit) {
                            tempOrders.add(orders.get(i));
                        } else {
                            break;
                        }
                    }
                }
                //计算缓存集合中订单的盈亏金额
                for (Order o : tempOrders) {
                    o.setProfitCount(this.getOrderCurrentProfit(o.getId()));
                }
                //按照盈亏金额进行冒泡排序 从大到小排序
                for (int x = 0; x < tempOrders.size(); x++) {
                    for (int y = 1; y < tempOrders.size(); y++) {
                        if (tempOrders.get(x).getProfitCount().doubleValue() < tempOrders.get(y).getProfitCount().doubleValue()) {
                            Order temp = tempOrders.get(y);
                            tempOrders.set(y, tempOrders.get(x));
                            tempOrders.set(x, temp);
                        }
                    }
                }
                return tempOrders.get(0);
            } else if (orders.size() == 1) {
                return orders.get(0);
            }
        }
        return null;
    }

    @Override
    public void handlerWaitDeferOrders(Integer orderId) throws Exception {
        //1.更改订单信息  总支付递延费金额和最新支付递延费日期
        //2.扣除用户账户余额。并产生资金日志
        //3.平台增加账户余额。并产生资金日志
        //4.推荐人的佣金分配和资金日志的记录
        //每万元递延费
        //查询订单状态
        Order or = orderMapper.selectByPrimaryKey(orderId);

        if (or.getStatus() == Order.STATUS.T3.code) {
            BigDecimal perTenThousandDeferFee = redisService.get(ConfigNID.DIYAN_FEE, BigDecimal.class);
            //每万元递延费(停牌)
            BigDecimal perTenThousandDeferFeeStop = redisService.get(ConfigNID.DIYAN_FEE_STOP, BigDecimal.class);
            //查询股票信息
            ModelRealTime model = QuotationEndpoint.realtime(or.getEquityCode());
            if (model != null && (model.getStatus().equals("1") || model.getStatus().equals("2"))) {
                //停牌单子,递延费8元
                //计算总已支付递延费
                or.setPaidDiyan(or.getPaidDiyan().add(or.getTradeCredit().multiply(perTenThousandDeferFeeStop)));
                or.setDiyanTime(or.getDiyanTime() + 1);
            } else if (model != null && model.getStatus().equals("0")) {
                //计算总已支付递延费
                or.setPaidDiyan(or.getPaidDiyan().add(or.getTradeCredit().multiply(perTenThousandDeferFee)));
                or.setDiyanTime(or.getDiyanTime() + 1);
            }
            or.setUnpaidDiyan(BigDecimal.ZERO);
            or.setDiyanDate(new Timestamp(new Date().getTime()));
            orderMapper.updateByPrimaryKeySelective(or);
            Account account = accountMapper.selectByUID(or.getUserId());
            //计算总已支付递延费
            BigDecimal amount = BigDecimal.ZERO;
            //扣减该订单的递延费
            if (model != null && (model.getStatus().equals("1") || model.getStatus().equals("2"))) {
                amount = or.getTradeCredit().multiply(perTenThousandDeferFeeStop);
            } else if (model != null && model.getStatus().equals("0")) {
                amount = or.getTradeCredit().multiply(perTenThousandDeferFee);
            }
            //停牌单子,递延费8元
            //记录资金记录
            AccountLog accountLog = AccountLog.buildLog(or.getUserId(), or.getId(), amount, AccountLog.TYPE.T12, account, "收取递延费" + amount + "元");
            if (accountLogMapper.insert(accountLog) != 1) {
                throw new BussinessException("收取递延费失败");
            }
            int i = accountMapper.updateAccount4Plat(amount.negate(), BigDecimal.ZERO, amount.negate(), amount, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, or.getUserId());
            if (i != 1) {
                throw new BussinessException("更新点买人账户金额出错");
            }
            //记录平台日志
            Account platAccount = accountService.getPlatAccount();
            //记录资金记录
            AccountLog accountLogP = AccountLog.buildLog(platAccount.getUserId(), or.getId(), amount, AccountLog.TYPE.T25, account, "平台获取递延费" + amount + "元");
            if (accountLogMapper.insert(accountLogP) != 1) {
                throw new BussinessException("平台获取递延费失败");
            }
            //记录平台资金日志
            // TODO: 2018-07-16 生成平台资金日志
            PlatAccountLog platAccountLog = new PlatAccountLog();

            int p = accountMapper.updateAccount4Plat(amount, BigDecimal.ZERO, amount, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, platAccount.getUserId());
            if (p != 1) {
                throw new BussinessException("更新平台账户金额出错");
            }
            BigDecimal totalDefer = redisService.get(CacheID.DEFER_FEE_COUNT, BigDecimal.class);
            if (totalDefer == null) {
                redisService.put(CacheID.DEFER_FEE_COUNT, amount);
            } else {
                totalDefer = totalDefer.add(amount);
                redisService.put(CacheID.DEFER_FEE_COUNT, totalDefer);
            }
            String operation = "";
            if (model != null && (model.getStatus().equals("1") || model.getStatus().equals("2"))) {
                operation = "订单ID: 【 " + or.getId() + " 】 于 " + DateUtils.dateStr4(new Date()) + " 收取递延费:【 " + or.getTradeCredit().multiply(perTenThousandDeferFeeStop) + " 】 元";
            } else if (model != null && model.getStatus().equals("0")) {
                operation = "订单ID: 【 " + or.getId() + " 】 于 " + DateUtils.dateStr4(new Date()) + " 收取递延费:【 " + or.getTradeCredit().multiply(perTenThousandDeferFee) + " 】 元";
            }
            orderOperationService.saveOrderOperation(or, operation);
//        doSellerFeeForDiyan(or);
            //代理商分佣
//        if (model != null && !model.getStatus().equals("0")) {
//            doAgentFeeForDiyan(or, true);
//        } else if (model != null && model.getStatus().equals("0")) {
//            doAgentFeeForDiyan(or, false);
//        }
        }
    }

    @Override
    public List<Order> selectTodayDealOrder() {
        return orderMapper.selectTodayDealOrder();
    }

    @Override
    public List<Order> selectTodaySettleOrder() {
        return orderMapper.selectTodaySettleOrder(Order.STATUS.T7.code);
    }

    /**
     * 补亏资金记录
     *
     * @param order
     * @param repair
     */
    private void doRepairLogs(Order order, BigDecimal repair) throws Exception {
        Account account = accountMapper.selectByUID(order.getUserId());
        //判断余额是否充足
        if (account.getAvailable().subtract(repair).compareTo(BigDecimal.ZERO) != 1) {
            throw new BussinessException("可用余额不足");
        }
        //记录资金记录
        //冻结履约保证金
        AccountLog accountLog = AccountLog.buildLog(order.getUserId(), order.getId(), repair, AccountLog.TYPE.T20, account, "补亏金额" + repair + "元");
        if (accountLogMapper.insert(accountLog) != 1) {
            throw new BussinessException("补亏金额失败");
        }

        //更新资金(0，-补亏金额，+补亏金额)
        int i = accountMapper.updateAccount(BigDecimal.ZERO, BigDecimal.ZERO, repair.negate(), repair, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, order.getUserId());
        if (i != 1) {
            throw new BussinessException("更新账户资金失败");
        }
    }

    @Override
    public void doRepairLoss(Order order, BigDecimal repair) throws Exception {
//        //递延阈值
//        String diyanLimit = redisService.get(ConfigNID.DIYAN_LIMIT);
//        //补亏 ，增加履约保证金，增加止损金额，
//        BigDecimal depositBefore = order.getDeposit();
//        BigDecimal stopLossBefore = order.getStopLossLine();
//        BigDecimal lossLimitBefore = order.getLossLimit();
//
//        order.setDeposit(order.getDeposit().add(repair));
//        order.setStopLossLine(order.getStopLossLine().subtract(repair));
//        order.setLossLimit(order.getDeposit().subtract(new BigDecimal(diyanLimit).multiply(order.getTradeCredit().multiply(new BigDecimal("10000")))).negate());
//        //补亏资金处理
//        doRepairLogs(order, repair);
//        orderMapper.updateByPrimaryKeySelective(order);
//        BigDecimal depositAfter = order.getDeposit();
//        BigDecimal stopLossAfter = order.getStopLossLine();
//        BigDecimal lossLimitAfter = order.getLossLimit();
//        //记录订单操作日志
//        OrderOperation orderOperation = new OrderOperation();
//        orderOperation.setOrderId(order.getId());
//        orderOperation.setOperation("补亏金额" + " 【 " + repair + " 】 元, " + "补亏前履约保证金: " + depositBefore + " 元," + "补亏后履约保证金: " + depositAfter + " 元," + "补亏前止损线: " + stopLossBefore + " 元，" + "补亏后止损线: " + stopLossAfter + " 元，" + " 补亏前递延条件：" + lossLimitBefore + " 元 " + "补亏后递延条件: " + lossLimitAfter + " 元");
//        orderOperation.setOperationTime(DateUtils.getNow());
//        orderOperationService.insert(orderOperation);
    }

//
//    /**
//     * 补亏资金记录
//     *
//     * @param order
//     * @param repair
//     */
//    private void doRepairLogs(Order order, BigDecimal repair) throws Exception {
//        Account account = accountMapper.selectByUID(order.getUserId());
//        //判断余额是否充足
//        if (account.getAvailable().subtract(repair).compareTo(BigDecimal.ZERO) != 1) {
//            throw new BussinessException("可用余额不足");
//        }
//        //记录资金记录
//        //冻结履约保证金
//        AccountLog accountLog = AccountLog.buildLog(order.getUserId(), order.getId(), repair, AccountLog.TYPE.T20, account, "补亏金额" + repair + "元");
//        if(accountLogMapper.insert(accountLog) !=1){
//              throw new BussinessException("补亏金额失败");
//          )
//
//        //更新资金(0，-补亏金额，+补亏金额)
//        int i = accountMapper.updateAccount(BigDecimal.ZERO, repair.negate(), repair, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, order.getUserId());
//        if (i != 1) {
//            throw new BussinessException("更新账户资金失败");
//        }
//    }


    @Override
    public void doModifyStopLoss(Order order, BigDecimal stopLosePrice, BigDecimal needDeposit, BigDecimal lastPrice) throws Exception {
        if (stopLosePrice.compareTo(order.getLoseStopPrice()) != 0) {//没有变动则略过
            //计算最大止损价格 = 最新价 - 履约保证金*最大止损保证金比例/买入数量
            BigDecimal maxStopLosePrice = lastPrice.subtract(order.getDeposit().multiply(order.getLossRate()).divide(new BigDecimal(order.getBuyDealNumber()), 2, BigDecimal.ROUND_DOWN));
            //Rule:1.传入止损价大于等于最大止损价格 则直接修改止损价格
            //     2.传入止损价小于最大止损价格 则修改止损价格，并要追加保证金
            BigDecimal subValue = BigDecimal.ZERO; //价格的差值（根据原订单止损价 和 已计算的最大止损价比 取最低值的差值）
            if(order.getLoseStopPrice().compareTo(maxStopLosePrice) == -1){
                if(stopLosePrice.compareTo(order.getLoseStopPrice()) == -1){
                    subValue = order.getLoseStopPrice().subtract(stopLosePrice);
                }
            }else{
                if(stopLosePrice.compareTo(maxStopLosePrice) == -1){
                    subValue = maxStopLosePrice.subtract(stopLosePrice);
                }
            }
            if(subValue.compareTo(BigDecimal.ZERO) == 1){
                //计算需要追加的保证金 = 止损差价 * 成交数量
                BigDecimal confNeedDeposit = subValue.multiply(new BigDecimal(order.getBuyDealNumber()));
                if (needDeposit.compareTo(confNeedDeposit) != 0) {
                    throw new BussinessException("请刷新页面重新操作");
                }
                Account account = accountMapper.selectByUID(order.getUserId());
                //资金记录
                AccountLog accountLog = AccountLog.buildLog(order.getUserId(), order.getId(), needDeposit, AccountLog.TYPE.T20, account, "修改止损追加保证金：" + needDeposit + "元");
                if (accountLogMapper.insert(accountLog) != 1) {
                    throw new BussinessException("修改止损追加保证金资金记录失败");
                }
                //更新账户资金
                if (accountMapper.updateAccount(BigDecimal.ZERO, BigDecimal.ZERO, needDeposit.negate(), needDeposit, BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ZERO, order.getUserId()) != 1) {
                    throw new BussinessException("修改止损追加保证金失败");
                }
            }

            orderMapper.updateByPrimaryKeySelective(new Order(t -> {
                t.setId(order.getId());
                t.setDeposit(order.getDeposit().add(needDeposit));
                t.setLoseStopPrice(stopLosePrice);
            }));
        }

    }

    @Override
    public List<Order> selectYesStrategy(Integer userId) throws Exception {
        return orderMapper.selectYesStrategy(userId);
    }

    @Override
    public Order selectByOne(Integer userId) throws Exception {
        return orderMapper.selectByOne(userId);
    }
}
